<template>
  <section class="ol_map_wrap">
    <!-- 插槽 -->
    <slot></slot>

    <!-- 地图 -->
    <section id="olMap" class="ol_map"></section>

    <!-- 图例 -->
    <lend ref="refLend" :currentPageType="currentPageType" :isShowLend="isShowLend" />

    <!--  气泡窗 -->
    <popup-common ref="refPopupCommon" :currentPageType="currentPageType" />

    <!-- 底部信息 -->
    <div class="copyright_info" v-show="true">
      <p>Copyright © CMDI.vip All Rights Reserved.</p>
      <ul>
        <li>
          <dl>
            <dt>经纬度：</dt>
            <dd>{{ currentLonlat }}</dd>
          </dl>
        </li>
        <li>
          <dl>
            <dt>当前层级：</dt>
            <dd>{{ currentZoomLevel }}</dd>
          </dl>
        </li>
      </ul>
    </div>
  </section>
</template>

<script setup name="gis">
// vue - core
import { ref, onMounted, defineEmits, nextTick } from "vue";
// map - core
import * as mapUtils from "./mapUtils.js";
import menuUtils from './menuUtils.js'
// 组件
import PopupCommon from "./components/popup/PopupCommon.vue"; // 气泡窗
import Lend from "./components/Lend.vue"; // 图例
// 工具
import { objIsEmpty } from "@/utils/index.js";
// 组件传参
import mittBus from "@/utils/mittBus"; // mitt
// 其他工具
import * as popupInner from "./components/popup/popupInner.js";

// 自定义事件
const emit = defineEmits([
  // 全局
  "getOlMapInstance",
  "getCurrentViewData",
  "reflashMap",
  // gis
  // ......
  // 投诉
  "getCircleData",
  "setCircleDialogData",
  'addArrowLine'
]);

const props = defineProps({
  currentPageType: {
    type: String,
    default: "",
  },
  isShowLend: {
    type: Boolean,
    default: true,
  },
});

const { proxy } = getCurrentInstance();

let myOlMap = null;

const refPopupCommon = ref(null);
const refLend = ref(null);

const currentZoomLevel = ref(0);
const currentLonlat = ref("");

const isRemoveMap = ref(true); // 判断渲染地图时是否移除当前地图要素

let currentSingleObjData = ref({}); // 当前检索到的数据

const mapCommonData = {
  minRenderZoom: mapUtils.minRenderZoom, // 最小渲染层级
};

// 地图加载完初始化做的一些操作
const mapInit = (olMap) => {
  // console.log('地图加载完初始化做的一些操作', olMap)
  myOlMap = olMap; // 赋值全局变量,为后续业务操作做准备

  // 地图加载完初始化做的一些操作[业务相关]
  emit("getOlMapInstance", olMap, mapCommonData); // 向外供出olMap实例,以及一些公共数据

  mapUtils.resetControls(olMap); // 初始化所有控件

  // 设置鼠标右键属性
  mapUtils.setContextmenu(
    olMap,
    (option) => {
      // console.log(option, mapUtils.menuMethods);
      setMenuMethods(option);
    },
    (next) => {
      // 根据具体页面配置菜单栏
      next(props.currentPageType);
    }
  );
};

// 设置鼠标右键菜单栏方法
const setMenuMethods = ({ option, feature, pixelPoint }) => {
  // console.log("设置鼠标右键菜单栏方法", option, feature, pixelPoint);

  // 点击地图隐藏气泡窗
  refPopupCommon.value.hidePopup();

  menuUtils.setMenuMethods(myOlMap, option, feature, pixelPoint, proxy)
};

// 地图加载完初始化后获取地图的一些信息
const getMapInitInfo = (olMap) => {
  // console.log("地图加载完初始化后获取地图的一些信息", olMap)

  // 获取可视区域数据
  emit("getCurrentViewData", olMap); // 地图加载时会自动触发一次 - 这里做测试

  // 圆数据
  emit("getCircleData", olMap);

  // 添加带箭头的线
  // emit('addArrowLine', olMap)
};

// 设置地图
const setOlmap = (olMap) => {
  mapEvent(olMap); // 地图事件
};

/**
 * 业务方法
 */
// 根据数据渲染Feature
const renderFeatureByData = (olMap, dataList, renderFeature) => {
  // console.log("根据数据渲染Feature", dataList);

  refPopupCommon.value.hidePopup();

  if (isRemoveMap.value) {
    // mapUtils.removeAllLayer(myOlMap); // 移除所有图层
    mapUtils.removeAllDefaultLayer(myOlMap); // 移除所有默认图层
  }

  setTimeout(() => {
    // console.log(dataList)
    dataList.forEach((item) => {
      renderFeature(olMap, item);
    });
  }, 500);
};

// 通过单条数据设置地图
const setMapBySingleData = async (olMap, itemData, fixData, renderFeature) => {
  // console.log('通过单条数据设置地图', olMap, itemData)

  if (fixData) {
    fixData(itemData);
  }

  // 选择数据隐藏气泡
  refPopupCommon.value.hidePopup();

  olMap.getView().setZoom(18);

  // 调用函数飞到指定的坐标
  flyToCoordinate(myOlMap, [itemData.longitude, itemData.latitude]);
  // mapUtils.flyToCoordinate(myOlMap, [itemData.longitude, itemData.latitude]);

  // 只显示一个Feature暂时使用此方案
  mapUtils.removeAllLayer(myOlMap); // 移除所有图层

  if (renderFeature) {
    renderFeature(olMap, [itemData]);
  }

  // 检索到当前要素
  setTimeout(() => {
    // 获取所有图层
    mapUtils.getAllFeature(olMap, (featureItem) => {
      // console.log(featureItem);
      // console.log(featureItem.get("type") === "Polygon");

      let featureData = {};

      switch (featureItem.get("type")) {
        case "Marker":
          featureData = featureItem.get("pointData");
          break;
        case "Curve":
          featureData = featureItem.get("curveData");
          break;
      }

      // console.log(featureData);

      if (featureData.cgi === itemData.cgi) {
        currentSingleObjData.value = { featureData, featureItem };
      }
    });
  }, 1000);

  // 将经纬度转换为屏幕坐标
  const pixelPoint = mapUtils.transformToPixelPoint(
    itemData.longitude,
    itemData.latitude
  );
  // console.log(pixelPoint)

  // 展示气泡窗
  mapUtils.setAutoPopup(pixelPoint, itemData, (popupObj) => {
    // console.log(popupObj)

    mapUtils.popupCommonConfig(
      olMap,
      pixelPoint,
      popupInner.commonPopupInner(popupObj),
      (e) => {
        const { target } = e; // 事件对象

        // 点击气泡窗获取更多
        if (target.getAttribute("data-function") === "getMore") {
          /* mittBus.emit("showPopupDialog", {
            popupData: itemData,
            currentPageType: props.currentPageType,
          }); */
          mittBus.emit("showPopupDialog", itemData);
        }
      }
    );
  });
};

/**
 * 接收其他组件派发的方法
 */
/**
 * 刷新地图
 * 各个组件如果需要刷新地图通过派发组件,最终到这个文件里面去做最终地图的刷新
 * resetFlag true 不带任何条件查询,查全部
 */
mittBus.on("reflashMap", (resetFlag) => {
  // console.log("刷新地图", resetFlag);

  // 判断是否需要带条件
  if (
    Boolean(resetFlag) &&
    myOlMap.getView().getZoom() > mapUtils.minRenderZoom
  ) {
    // 如果需要带条件,需要出发点全局派发事件去修改按钮dom
    mittBus.emit("resetBtn");
  }

  // 最终的刷新需要自组件派发事件到父组件完成派发
  emit("reflashMap", resetFlag, () => {
    nextTick(() => {
      setTimeout(() => {
        // 刷新完成之后,需要对检索到的数据去做定位
        if (!objIsEmpty(currentSingleObjData.value)) {
          // console.log("当前有检索条件", currentSingleObjData.value);

          let { featureData, featureItem } = currentSingleObjData.value;
          // console.log(featureItem);

          // 置顶图层
          mapUtils.featureToMaxTop(myOlMap, featureItem);
        }
      }, 1000);
    });
  });
});

// 取消绘制(点线面)
mittBus.on("cancelDrawInteraction", () => {
  // console.log('drawPolygon')

  mapUtils.cancelDrawInteraction(myOlMap); // 绘制多边形
});

// 绘制多边形
mittBus.on("drawPolygon", () => {
  // console.log('drawPolygon')

  mapUtils.drawPolygon(myOlMap); // 绘制多边形
});

// 取消绘制多边形
mittBus.on("cancelPolygon", () => {
  // console.log('取消绘制多边形')

  mapUtils.cancelPolygon(myOlMap); // 绘制多边形
});

// 测距
mittBus.on("testDistance", (next) => {
  // console.log("测距");

  // 测距
  mapUtils.testDistance(myOlMap, next);
});

// 取消测距
mittBus.on("cancelTestDistance", () => {
  // console.log("取消测距");

  mapUtils.cancelTestDistance(myOlMap); // 取消测距
});

/**
 * menu方法接收
 */
// 显示当前要素信息
mittBus.on("singleFeaturesClick", ({ feature, pixelPoint }) => {
  // console.log("显示当前要素信息", feature, pixelPoint);

  if (props.currentPageType === "complain") {
    emit("setCircleDialogData", feature);

    return;
  }
  // 点击单个feature - map - click事件
  singleFeaturesClick(myOlMap, feature, pixelPoint);
});

/**
 * 地图工具方法
 */
// 地图事件
const mapEvent = (olMap) => {
  // 监听鼠标移动事件
  olMap.on("pointermove", (e) => {
    // 鼠标移动到feature区域时变为手形
    let pixel = olMap.getEventPixel(e.originalEvent);
    let hit = olMap.hasFeatureAtPixel(pixel);
    olMap.getTargetElement().style.cursor = hit ? "pointer" : "";

    currentLonlat.value = mapUtils.transformToLonlat(e.coordinate);
  });

  // 监听鼠标单击事件
  olMap.on("singleclick", (e) => {
    // console.log("点击地图", mapUtils.transformToLonlat(e.coordinate));

    // 点击地图隐藏气泡窗
    refPopupCommon.value.hidePopup();

    // 点击地图隐藏右键菜单
    mapUtils.resetContextMenu();

    // const pixelPoint = e.coordinate; // 屏幕坐标
    let pixel = olMap.getEventPixel(e.originalEvent);
    let featureList = olMap.getFeaturesAtPixel(pixel); // 点击时获取所有features

    const currentShapeFeature = (shape) => {
      return featureList.filter((item) => item.get("type") === shape);
    };

    const judgeShape = (shape) => {
      return JSON.stringify(currentShapeFeature(shape)) !== "[]";
    };

    // 如果feature数组存在(不为空)
    if (featureList) {
      // 点击单个feature
      if (featureList.length === 1) {
        // console.log("无重叠,单个feature", featureList);

        // refPopupCommon.value.showPopup(); // 需要气泡时弹出

        // 不显示气泡窗的要素禁止弹窗
        if (currentShapeFeature("Circle").length !== 0) {
          refPopupCommon.value.hidePopup();
        }

        // 点击单个feature - map - click事件
        singleFeaturesClick(olMap, featureList[0], e.coordinate);
      }

      // 多个feature
      if (featureList.length > 1) {
        // console.log("有重叠,多个feature", featureList);

        // 如果重叠区存在圆形
        if (judgeShape("Circle")) {
          // console.log('点击圆区域内要素')
          let pointFeatureList = currentShapeFeature("Marker")

          // 圆里面只有2个要素
          if (featureList.length === 2) {
            let pointFeature = pointFeatureList[0]
            // console.log(pointFeature)
            singleFeaturesClick(myOlMap, pointFeature, e.coordinate);
          } else {
            refPopupCommon.value.setFeaturesPopup(
              olMap,
              e.coordinate,
              featureList
            );
          }

          // setCircleDialogData(currentShapeFeature("Circle")[0]);
        } else if (judgeShape("Polygon")) {
          let featureItem = featureList.filter(
            (item) => item.get("type") === "Polygon"
          );
          setPolygonDialogData(featureItem[0]);
        } else {
          // 点击扇形弹出气泡
          if (
            featureList[0].get("type") === "Curve" ||
            featureList[0].get("type") === "Marker"
          ) {
            // refPopupCommon.value.showPopup(); // 需要气泡时弹出
            refPopupCommon.value.setFeaturesPopup(
              olMap,
              e.coordinate,
              featureList
            );
          }
        }
      }
    }
  });

  // 监听鼠标拖动地图事件
  olMap.on("moveend", (e) => {
    // console.log('拖拽移动触发事件', e)

    let view = myOlMap.getView();
    let zoom = view.getZoom();
    currentZoomLevel.value = zoom.toFixed(2);
    // console.log("当前缩放级别为：", zoom, mapUtils.minRenderZoom);

    mittBus.emit("getCurrentZoom", {
      zoom,
      minRenderZoom: mapUtils.minRenderZoom,
    });

    switch (props.currentPageType) {
      case 'complain':
        emit("getCurrentViewData", olMap); // 刷新地图
        break
    }

    // emit("getCurrentViewData", olMap); // 刷新地图
  });
};

// 点击单个feature - map - click事件
const singleFeaturesClick = (olMap, featureItem, pixelPoint) => {
  // console.log("无重叠,单个feature", featureItem);

  let popupData = null;

  // 点击点标注
  if (featureItem && featureItem.get("type") === "Marker") {
    // console.log('Marker点标注', featureItem);

    popupData = featureItem.get("pointData");
    // console.log('获取点标注数据', popupData)

    refPopupCommon.value.setCommonPopup(olMap, pixelPoint, popupData);
  }

  // 点击扇形区域
  if (featureItem && featureItem.get("type") === "Curve") {
    // console.log('点击扇形区域', featureItem);

    popupData = featureItem.get("curveData");
    // console.log('获取扇形区数据', popupData)

    refPopupCommon.value.setCommonPopup(olMap, pixelPoint, popupData);
  }

  // 点击圆形区域
  if (featureItem && featureItem.get("type") === "Circle") {
    // console.log("点击圆形区域", featureItem);

    setCircleDialogData(featureItem);
  }

  // 点击多边形
  if (featureItem && featureItem.get("type") === "Polygon") {
    // console.log("点击多边形", featureItem.get("polygonData"));

    const polygonData = featureItem.get("polygonData");

    // 网格
    if (polygonData.businessType === "grid") {
      // console.log("点击网格数据", polygonData);
      // return;
    }

    // 弹出多边形数据
    setPolygonDialogData(featureItem);
  }
};

// 点击圆形区域获取数据
const setCircleDialogData = (feature) => {
  // refCircleDetailDialog.value.show();

  let circleData = feature.get('circleData')
  // console.log(circleData)

  emit("setCircleDialogData", circleData);
};

// 弹出多边形数据
const setPolygonDialogData = (featureItem) => {
  const { coords, lonlat, name } = featureItem.get("polygonData");
  // console.log(coords);

  mittBus.emit("setMyPolygonInfoDialog", { lonlat, name });
};

/**
 * 地图方法供出
 */

// 获取可视区域坐标
const getCurrentViewPosition = (olMap) => {
  return mapUtils.getCurrentViewPosition(olMap);
};

// 添加圆
const addCircle = (olMap, item, isFlicker) => {
  mapUtils.addCircle(olMap, item, isFlicker);
};

// 加载kml
const loadKML = (olMap, text) => {
  mapUtils.loadKML(olMap, text);
};

// 移除所有图层
const removeAllLayer = (olMap) => {
  // console.log(olMap, type);

  mapUtils.removeAllLayer(olMap);
};

// 根据类型移除图层
const removeLayerByType = (olMap, type) => {
  // console.log(olMap, type);

  mapUtils.removeLayerByType(olMap, type); // 移除所有图层
};

// 批量添加点
const addPoint = (olMap, pointList, isIcon, src) => {
  mapUtils.addPoint(olMap, pointList, isIcon, src);
};

// 设置 Features 样式
const setFeaturesStyle = (fillColor, strokeColor) => {
  return mapUtils.setFeaturesStyle(fillColor, strokeColor);
};

// 批量添加扇形
const addCurve = (olMap, pointList, isResetStyle) => {
  if (isResetStyle) {
    mapUtils.addCurve(olMap, pointList, (item) => {
      return isResetStyle(item);
    });
  } else {
    mapUtils.addCurve(olMap, pointList);
  }
};

const flyToCoordinate = (OlMap, lonlat) => {
  mapUtils.flyToCoordinate(OlMap, lonlat);
};

// 创建多边形
const createPolygon = (olMap, polygon, gridData, next, style) => {
  // console.log("createPolygon", olMap, gridData, polygon);

  let lonlat = polygon;

  let coords = polygon.map((item) => {
    return mapUtils.transformToPixelPoint(item[0], item[1]);
  });
  // coords = [coords];
  // console.log(coords);

  const polygonData = {
    businessType: "grid",
    ...gridData,
  };

  mapUtils.createPolygon(olMap, { coords, lonlat, polygonData }, next, style);
};

// 创建文字图层
const addTextPoint = (olMap, text, position, textOverlayConfig = {}, isRemove) => {
  mapUtils.addTextPoint(olMap, text, position, textOverlayConfig, isRemove);
};

// 获取多边形中心点
const getPolygonCenter = (feature) => {
  return mapUtils.getPolygonCenter(feature);
};

// 添加带箭头的线
const addArrowLine = (olMap, position, src) => {
  mapUtils.addArrowLine(olMap, position, src)
}

/**
 * vue生命周期函数
 * 挂载后触发
 */
onMounted(() => {
  const olMap = mapUtils.initOlMap("olMap"); // 初始化地图

  mapInit(olMap); // 地图加载完初始化做的一些操作
  getMapInitInfo(olMap); // 地图加载完初始化后获取地图的一些信息
  setOlmap(olMap); // 设置地图
});

/**
 * 暴露方法
 */
defineExpose({
  renderFeatureByData, // 根据数据渲染Feature
  setMapBySingleData, // 通过单条数据设置地图

  // 地图方法供出
  getCurrentViewPosition, // 获取可视区域坐标
  addCircle, // 添加圆
  loadKML, // 加载kml
  removeAllLayer, // 移除所有图层
  removeLayerByType, // 根据类型移除图层
  addPoint, // 批量添加点
  addCurve, // 批量添加扇形
  createPolygon, // 创建多边形
  flyToCoordinate, // 飞到指定的坐标
  setFeaturesStyle, // 设置 Features 样式
  addTextPoint, // 创建文字图层
  getPolygonCenter, // 获取多边形中心点
  addArrowLine,  // 添加带箭头的线
});
</script>

<style lang="scss">
$zoomMargin: 10em;

.ol_map_wrap {
  position: absolute;
  width: 100%;
  height: 100%;
  min-width: 1250px;

  .ol_map {
    width: 100%;
    height: 100%;
    // overflow: hidden;

    .flicker_point {
      height: 50px;
      width: 50px;
      border-radius: 25px;
      background: rgba(255, 0, 0, 0.9);
      transform: scale(0);
      animation: flickerAnimation 3s;
      animation-iteration-count: infinite;
      cursor: pointer;
    }

    @keyframes flickerAnimation {
      to {
        transform: scale(2);
        background: rgba(0, 0, 0, 0);
      }
    }

    .ol-viewport {
      overflow: initial !important;
    }

    // 控件相关
    .ol-overlaycontainer-stopevent {
      // 全屏
      /* .ol-full-screen {
        position: absolute;
        top: -34px;
        right: 108px;
      } */

      // 缩放
      .ol-zoom,
      .ol-zoomslider {
        left: initial;
        right: 0.5em;
      }

      .ol-zoom {
        top: calc(0.5em + $zoomMargin);
      }

      .ol-zoomslider {
        top: calc(4.5em + $zoomMargin);
      }

      // 比例尺
      .ol-scale-line {
        position: absolute;
        bottom: 76px;
        background: initial;
      }

      /* // 鹰眼
      .ol-overviewmap {
        position: absolute;
        left: 0;
        bottom: 20px;

        .ol-overviewmap-map {
          width: 100px;
          height: 100px;
        }
      } */
    }
  }
}

.menu_wrap {
  padding: 3px;
  max-height: 157px;
  background: rgba(255, 255, 255, 0.8);
  border: solid 1px #777777;
  border-radius: 5px;
  overflow: auto;

  ul {
    padding-bottom: 3px;

    li {
      padding: 5px 10px;
      font-size: 12px;
      color: #000;
      border-radius: 3px 3px 0 0;
      cursor: pointer;
      transition: 0.3s linear;

      &:hover {
        color: #715f5f;
        background: rgba(128, 128, 128, 0.25);
        transition: 0.3s linear;
      }

      &:not(:last-child) {
        margin-bottom: 3px;
        border-bottom: solid 1px #b3b3b3;
      }
    }
  }
}

.copyright_info {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  min-width: 800px;
  min-height: 20px;
  display: flex;
  justify-content: space-between;
  padding: 0 25px 0 12px;
  z-index: 1;
  background: #8a8888c4;

  p,
  dt,
  dd {
    height: 25px;
    line-height: 28px;
    font-size: 12px;
  }

  ul {
    li {
      display: inline-block;

      &:first-child {
        dd {
          min-width: 350px;
        }
      }

      dl {

        dt,
        dd {
          display: inline-block;
        }
      }
    }
  }
}
</style>
